﻿using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace Red.Controls.Shell
{
    /// <summary>
    ///     Dialog allowing the user to enter a single line of text
    /// </summary>
    public partial class TextInputDialog : RedDialog
    {
        #region Data
        
        private static string _defaultTitle = "Text input";
        private static string _defaultLabel = "Enter text";

        #endregion Data

        #region Properties

        public static readonly DependencyProperty LabelProperty =
            DependencyProperty.Register( "Label", typeof( string ), typeof( TextInputDialog ), new FrameworkPropertyMetadata( "Enter name" ) );

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register( "Text", typeof( string ), typeof( TextInputDialog ), new FrameworkPropertyMetadata( string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault ) );

        public static readonly DependencyProperty ShowDirectoryPickerProperty =
            DependencyProperty.Register( "ShowDirectoryPicker", typeof( bool ), typeof( TextInputDialog ) );

        /// <summary>
        ///     Label displayed above text input field
        /// </summary>
        public string Label
        {
            get { return (string)GetValue( LabelProperty ); }
            set { SetValue( LabelProperty, value ); }
        }

        /// <summary>
        ///     Content of text input field
        /// </summary>
        public string Text
        {
            get { return (string)GetValue( TextProperty ); }
            set { SetValue( TextProperty, value ); }
        }

        /// <summary>
        /// Display a button inside the text input field that invokes the directory picker
        /// </summary>
        public bool ShowDirectoryPicker
        {
            get { return (bool)GetValue( ShowDirectoryPickerProperty ); }
            set { SetValue( ShowDirectoryPickerProperty, value ); }
        }

        #endregion Properties

        #region C-tor

        public TextInputDialog( FrameworkElement elem )
            : base( elem )
        {
            InitializeComponent();
        }

        #endregion C-tor

        #region Public methods

        public static string Show( FrameworkElement elem, string initialText, string label = null, string title = null, bool showDirectoryPicker = false )
        {
            var msg = new TextInputDialog( elem ) 
            {
                Type = RedDialogType.OkCancel, 
                Label = label ?? _defaultLabel, 
                Title = title ?? _defaultTitle,
                Text = initialText,
                ShowDirectoryPicker = showDirectoryPicker
            };

            if ( msg.Show() )
                return msg.Text;
            else
                return null;
        }

        public static async Task<string> ShowAsync( FrameworkElement elem, string initialText, string label = null, string title = null, bool showDirectoryPicker = false )
        {
            var msg = new TextInputDialog( elem ) 
            {
                Type = RedDialogType.OkCancel, 
                Label = label ?? _defaultLabel, 
                Title = title ?? _defaultTitle,
                Text = initialText,
                ShowDirectoryPicker = showDirectoryPicker
            };

            bool res = await msg.ShowAsync();

            if ( res )
                return msg.Text;
            else
                return null;
        }

        #endregion Public methods

        #region Event Handlers

        private void OnFocus( object sender, RoutedEventArgs e )
        {
            TextBox textbox = sender as TextBox;
            ButtonTextbox btb = sender as ButtonTextbox;

            textbox?.SelectAll();
            btb?.SelectAll();
        }

        private void OnLoaded( object sender, RoutedEventArgs e )
        {
            UIElement element = ( (UIElement)sender );

            // There are multiple textboxes, but we only care about the one that is visible
            if ( element.Visibility == Visibility.Visible )
            {
                // OnLoaded is called after the constructor but before the property initialiser
                // So we will wrap the focus call in a dispatcher event to ensure whatever default
                // text has been specified will be in the textbox when the focus event happens
                Dispatcher.BeginInvoke
                (
                    (Action)delegate
                    {
                        element.Focus();
                    }
                );
            }
        }

        #endregion Event Handlers
    }
}
